//=======================================================================================
// GetOption.hh
// --------------------------------------------------------------------------------------
//
//
// K. James Durbin    
//========================================================================================
//.......1.........2.........3.........4.........5.........6.........7.........8.........9
//

#ifndef _GETOPTION
#define _GETOPTION

#include "LocalSTL.hh"
#include "ParseUtils.hh"

#define OPTION_EOF '0'

//-------------------------------------------------------------------
// GetOption
//-------------------------------------------------------------------
// Parses command line options.  Currently only handles single letter arguments.  Example 
// of use is given below:
//
// void PrintHelp(){
//  cout<<"This program takes options d,v,s,e,and f."<<endl;
// }
//
// int main(int argc, char**argv)
// {
//   bool    bDebug,bVerbose;
//   string  SCFPath;
//   int     EXPNum;
//   float   SomeFloat;
//
//   GetOption Parser(argc,argv,"dvs:e:f:");
//  
//   char theOption;
//   while((theOption = Parser.NextOption()) != EOF){
//     switch(theOption){
//     case 'd': bDebug = true; break;
//     case 'v': bVerbose = true; break;
//     case 's': SCFPath =  Parser.GetArg(); break;
//     case 'e': EXPNum = Parser.GetIntArg(); break;
//     case 'f': SomeFloat = Parser.GetFloatArg(); break;
//     default:  PrintHelp(); break;
//     }
//   }
// }
//
// Returns OPTION_EOF when options have been exhausted.  Returns '?' when 
// the options are invalid or if -? has been entered on the command 
// line.  -? and -h are always valid options and so calling program 
// should always handle these cases by printing some form of help.   
//
// One day, I will rewrite this crude hack to accept long options like --expnum. 
// The messy part about doing that is that you have to write something more 
// complicated for the case statements, since you can't case on strings.  
// 
class GetOption{
public:

  bool            mValid;
  vector <char>   mOptions;
  vector <string> mArgs;
  string          mOptDef;
  int             mOptIdx;
  int             mArgIdx;

  string          mFormattedOptions;

  GetOption(int argc, char **argv, const char* optDef);
  
  char     NextOption();
  string   NextArg();  // Soon to be depreciated. 

  string   GetStringArg(){
	 return(NextArg());
  }
  float    GetFloatArg(){
	 return(atof(NextArg().c_str()));
  };
  int      GetIntArg(){
	 return(atoi(NextArg().c_str()));
  }

  string   GetFreeArg();


  // Sort of a Perl style GetOptions function.   Handles long options. 
  // Example:
  //
  // if (!GetOptions(argc,argv,
  //                "samples|s=i",OptNumSamples,
  //                "query|q=s", OptQuery,
  //                "interior|I=b",OptSampleInterior,
  //                "cutoff|c=f",OptCutoff,
  //                "output|p=s",OptOutName)){
  //     PrintHelp();
  //  }
  //
  // Every option must have both a long and a short version and a type. 
  // Valid types are:
  // i   integer
  // f   float
  // s   string
  // b   boolean (no argument is passed, variable is set to true if option present, false otherwise). 
  //
  bool GetOptions(int argc,char**argv,...);


};


#endif
